<template>
	<!-- tour-content-out-box start -->
	<div>
		<div v-if="needCover && showGuide" class="bbx-guide-cover" :style="coverStyle" @click="coverClick">
		</div>
		<div v-if="needCover && showGuide" class="bbx-guide-virtualDom" :style="coverInsideDomStyle" @click.stop="coverInsideClick"></div>
		<div
			v-show="showGuide"
			ref="guideCom"
			class="tour-content-out-box"
			:class="[guideMounted && showGuide ? 'have-mounted' : '', guideSizeClass[guideSize],diyClass]"
			:style="guideStyle">
			<!-- <div
				v-if="arrowDirection == 'up'"
				class="normal-arrow-top tour-arrow"
				:style="arrowStyle" />
			<div
				v-if="arrowDirection == 'down'"
				class="normal-arrow-down tour-arrow-down"
				:style="arrowStyle" />
			<div
				v-if="arrowDirection == 'left'"
				class="normal-arrow-left tour-arrow"
				:style="arrowStyle" /> -->
			<div
				:class="[`normal-arrow-${arrowDirection}`, 'tour-arrow']"
				:style="arrowStyle" />
			<div class="tour-content-box">
				<div
					v-if="haveStep"
					class="tour-left-tips">
					{{ `${nowStep}/${totalStep}` }}
				</div>
				<div
					class="tour-content"
					@click="watchContentClick($event)">
					<div class="flex-x tour-content-head">
						<div class="flex-1 overHideCon-1 tour-content-title">
							{{ title }}
						</div>
						<i
							v-if="showCloseIcon"
							class="iconfont icon-close"
							@click.prevent="
								stopStep().then(() => {
									showGuide = false;
								})
							" />
					</div>
					<slot name="diyContent">
						<div class="tour-content-con">
							{{ content }}
						</div>
					</slot>
				</div>
			</div>
			<div class="tour-bottom">
			  
				<div class="tour-bottom-left">
				  
					<div
						v-if="leftBtn && leftBtnFn"
						class="text overHideCon-1"
						@click.prevent="onLeftBtnClickHandler">
						{{ leftBtn }}
					</div>
				  		  
					<div
						v-else-if="needPreviousStep && nowStep > 1"
						class="text overHideCon-1"
						@click.prevent="previousStep(nowStep).then(() => {
							showGuide = false;
						})"
					>
						{{ previousStepBtn }}
					</div>
				  
				</div>
			  
				<div class="tour-bottom-right">
				  
					<div
						v-if="totalStep > 1 && nowStep > 0 && nowStep < totalStep"
						class="btns overHideCon-1"
						@click.prevent="
							nextStep(nowStep).then(() => {
								showGuide = false;
							})"
					>
						{{nextStepBtn}}
					</div>
					
					<div
						v-if="lastFinish === 1 ? nowStep == totalStep : lastFinish === 0"
						class="btns overHideCon-1"
						@click.prevent="
							finishBtnFn().then(() => {
								showGuide = false;
							})"
					>
						{{ finishBtn }}
					</div>
				  
				</div>
			  
			</div>
		</div>
	</div>
	<!-- tour-content-out-box end -->
</template>
<script>
import { t } from '@src/locales'
import _ from 'lodash';
/* mixin */
import { VersionControlOtherMixin } from '@src/mixins/versionControlMixin'

/**
 * @module GuideCompoment
 * @desc 全局引导弹窗 需结合vue全局方法$GuideFaster调用以下均是arr每个object所需要的值
 * @des 所谓流程参数适用于一个流程引导通用的配置,如果配置流程参数则该引导流程下的所有引导内容无该参数时默认适用流程参数内的配置(默认为数组参数第一个下的stepTotalSetting)
 * @vue-prop {Number | String} totalStep=1 引导的全部流程数(默认拿取当前数组的长度也可自定义)
 * @vue-prop {Number | String} nowStep=1 当前引导的流程数量
 * @vue-prop {Number | String} [title] 引导的标题
 * @vue-prop {Number | String} [content] 引导的内容
 * @vue-prop {Boolean} [needCover = false] 需要遮盖层突出引导元素(可被流程参数配置)
 * @vue-prop {Boolean} [showCloseIcon = true] 是否显示关闭icon
 * @vue-prop {Boolean} [canUse = false] 已舍弃 引导的元素是否可以点击(一般配合needCover使用)
 * @vue-prop {Number | String} [finishBtn = 'ok'] 引导弹窗的结束按钮的内容(可被流程参数配置)
 * @vue-prop {Number | String} id 存储引导元素的DomId
 * @vue-prop {Number | String} domId 需要引导的元素的DOM id
 * @vue-prop {Function} domObj  函数返回需要引导的元素的DOM实例,优先级高于domId
 * @vue-prop {Function} [stopStep] 引导元素关闭时(右上角close)触发的钩子函数
 * @vue-prop {Function} [finishBtnFn] 引导元素点击finishBtn触发的钩子
 * @vue-prop {Function} [watchContentClick] 引导元素内容的点击事件触发的钩子
 * @vue-prop {Function} [nextStep] 点击下一步触发的钩子函数
 * @vue-prop {Boolean} haveStep = false 是否需要步骤引导(可被流程参数配置)
 * @vue-prop {Boolean} [inside = false] 当needCover为true时希望高亮父元素且引导元素指向内部子元素的某个元素
 * @vue-prop {Function} [insideDom] 返回需要inside的子元素DOM实例
 * @vue-prop {Function} [outsideParent] 返回需要inside的子元素的父元素的DOM实例
 * @vue-prop {Boolean} [copyDom = false] 已舍弃 针对部分特殊的引导元素需要复制新的引导元素到当前组件(使用时css样式需单独写入组件)
 * @vue-prop {String} [direction = 'column'] 引导的方向 ('column':纵向, 'row':'横向')(可被流程参数配置)
 * @vue-prop {String} [guideSize = 'size-1'] 引导的样式大小(@vue-data guideSizeClass)(可被流程参数配置)
 * @vue-prop {Number} [lastFinish = 0] 0 无论何时都显示结束引导按钮 1 如果是多步骤引导只在最后一步显示结束引导按钮 2 无论何时都不显示结束引导按钮(可被流程参数配置)
 * @vue-data {Object} guideSizeClass 引导的样式枚举(可被流程参数配置)
 * @vue-data {Boolean} needPreviouseStep 需要上一步流程按钮(可被流程参数配置)
 * @vue-data {String} previousStepBtn 上一步流程按钮文案(可被流程参数配置)
 * @vue-data {String} nextStepBtn 下一步流程按钮文案(可被流程参数配置)
 * @vue-data {Function} domClick 返回蒙层的点击事件以及被引导元素遮盖物的点击事件
 * @vue-data {String} diyClass 自定义样式
 */
import { defineComponent } from 'vue';

export default defineComponent({
	name: 'GuideCompoment',
	mixins: [VersionControlOtherMixin],
	props: {
		totalStep: {
			type: [Number, String],
			default: 1,
		},
		nowStep: {
			type: [Number, String],
			default: 1,
		},
		title: {
			type: [Number, String],
			default: '',
		},
		content: {
			type: [Number, String],
			default: '',
		},
		needCover: {
			type: Boolean,
			default: false,
		},
		showCloseIcon: {
			type: Boolean,
			default: true,
		},
		// 已舍弃
		canUse: {
			type: Boolean,
			default: false,
		},
		finishBtn: {
			type: [Number, String],
			default: 'ok',
		},
		id: {
			type: [Number, String],
			default: '',
		},
		domId: {
			type: [Number, String],
			default: '',
		},
		domObj: {
			type: Function,
		},
		stopStep: {
			type: Function,
		},
		finishBtnFn: {
			type: Function,
		},
		watchContentClick: {
			type: Function,
		},
		nextStep: {
			type: Function,
		},
		haveStep: {
			type: Boolean,
			default: false,
		},
		inside: {
			type: Boolean,
			default: false,
		},
		// 已舍弃
		copyDom: {
			type: Boolean,
			default: false,
		},
		direction: {
			type: String,
			default: 'column',
		},
		guideSize: {
			type: String,
			default: 'size-1',
		},
		lastFinish: {
			type: Number,
			default: 0,
		},
		// 拓展
		insideDom: {
			type: Function,
		},
		outsideParent: {
			type: Boolean,
			default: false,
		},
		needPreviousStep: {
			type: Boolean,
			default: false
		},
		previousStep: {
			type: Function,
		},
		previousStepBtn: {
			type: String,
			default: t('common.base.steps.previous')
		},
		nextStepBtn: {
			type: String,
			default: t('common.base.steps.next')
		},
		leftBtn: {
			type: String
		},
		leftBtnFn: {
			type: Function
		},
		domClick: {
			type: Function,
		},
		diyClass:{   //自定义class
			type: String,
			default: '',
		}
	},
	data () {
		return {
			showGuide: true,
			guideStyle: '',
			arrowStyle: '',
			guideDom: {},
			guideCoverDom: {},
			loop: null,
			arrowDirection: 'up',
			guideMounted: false,
			guideSizeClass: {
				'size-1': 'size-240',
				'size-2': 'size-280',
				'size-3': 'size-320',
				'size-4': 'size-350',
			},
			clickCount:0
		};
	},
	computed: {
		coverStyle () {
			try {
				const { left, top, width, height } = this.guideCoverDom;
				return `top:${top}px;left:${left}px;width:${width}px;height:${height}px;transform: translate(calc(-50% + ${width / 2}px), calc(-50% + ${height / 2}px));`
			} catch (error) {
				console.error(error, 'error try catch coverStyle');
				return ''
			}
		},
		coverInsideDomStyle () {
			try {
				const { left, top, width, height } = this.guideDom;
				return `top:${top}px;left:${left}px;width:${width}px;height:${height}px;transform: translate(calc(-50% + ${width / 2}px), calc(-50% + ${height / 2}px));`
			} catch (error) {
				console.error(error, 'error try catch coverInsideDomStyle');
				return ''
			}
		}
	},
	watch: {
		showGuide (newVal) {
			if (!newVal) {
				this.clearGuide();
			}
		},
	},
	mounted () {
		this.initLoop();
	},
	beforeUnmount () {
		this.clearGuide();
	},
	methods: {
		clearGuide () {
			// 已舍弃 s
			// if (this.needCover) {
			// 	let dom_ = this.domObj ? this.domObj() : document.getElementById(`${this.domId}`);
			// 	dom_ && dom_.classList.remove('guide-point');
			// 	if (this.copyDom) {
			// 		try {
			// 			document.getElementById('vmDom').children[0].remove();
			// 		} catch (error) {
			// 			console.error(error, 'error try catch');
			// 		}
			// 	}
			// }
			// 已舍弃 e
			this.showGuide = false;
			clearInterval(this.loop);
		},
		coverClick () {
			// 为了防止遮盖层影响页面做backup 点击蒙层6次关闭引导
			this.clickCount++;
			if (this.clickCount > 5) {
				this.clearGuide();
				this.clickCount = 0;
			}
			this.domClick && this.domClick({ type: 'cover' })
		},
		coverInsideClick () {
			this.domClick && this.domClick({ type: 'coverInsideDom' })
		},
		initLoop () {
			this.loop = setInterval(() => {

				// TODO：纯客服云版本暂不显示引导
				if (this._isNotShowGuide) {
					return (this.showGuide = false);
				}

				if (!document.getElementById(this.domId) && !this.domObj) return (this.showGuide = false);
				this.showGuide = true;
				// console.log(this.domObj(), 321321);
				let res_;
				let guideDom = {
					width: 350,
					height: 400,
				};
				let guidePartentDom;
				let dom;

				try {
					dom = this.domObj ? this.domObj() : document.getElementById(`${this.domId}`);
					if (dom) (res_ = dom.getBoundingClientRect()), (guidePartentDom = dom.getBoundingClientRect());
					if (this.inside && this.insideDom) res_ = this.insideDom().getBoundingClientRect();
					guideDom = this.$refs.guideCom.getBoundingClientRect();
				} catch (error) {
					console.error(error, 'error try catch');
				}
				// 被引导的元素位置不变化的话停止引导组件的渲染
				if (
					!res_ ||
          (this.guideDom &&
            res_ &&
            this.guideDom.top == res_.top &&
            this.guideDom.left == res_.left &&
            this.guideDom.height == res_.height &&
            this.guideDom.width == res_.width)
				)
					return;
				// 默认遮挡needCover的引导元素的父元素
				this.guideCoverDom = dom.getBoundingClientRect();
				let style_ = '';
				// 已舍弃 s
				// if (this.needCover && this.copyDom) {
				// 	// 针对部分无法sticky的父元素使用直接复制引导dom元素 需要引入css不推荐使用
				// 	try {
				// 		document.getElementById('vmDom').children[0].remove();
				// 	} catch (error) {
				// 		console.error(error, 'error try catch');
				// 	}
				// 	let dom_clone = dom.cloneNode(true);
				// 	dom_clone.setAttribute('id', '');
				// 	dom_clone.style.cssText = `position: fixed;z-index: 997;top:${res_.top}px;left:${res_.left}px;width:${res_.width}px;height:${res_.height}px;background:#fff;`;
				// 	document.getElementById('vmDom').appendChild(dom_clone);
				// }
				// if (this.needCover && !this.copyDom) {
				// 	let dom_ = this.domObj ? this.domObj() : document.getElementById(`${this.domId}`);
				// 	if (!dom_) return;
				// 	dom_.classList.add('guide-point');
				// }
				// 已舍弃 e

				if (this.direction == 'row') {
					if (document.documentElement.clientWidth - res_.left - res_.width >= guideDom.width + 8) {
						// 右侧有足够的位置
						this.arrowDirection = 'left';
						if (!this.inside) {
							style_ = `${style_};left:${res_.left + res_.width + 8 || 0}px`;
						} else {
							if (this.outsideParent) {
								style_ = `${style_};left:${guidePartentDom.left + guidePartentDom.width + 8 || 0}px;z-index:998`;
							} else {
								style_ = `${style_};left:${res_.left + res_.width + 8 || 0}px;z-index:998`;
							}
						}
					} else {
						// 左侧有足够的位置
						this.arrowDirection = 'right';

						if (!this.inside) {
							style_ = `${style_};left:${res_.left - guideDom.width - 8}px`;
						} else {
							if (this.outsideParent) {
								style_ = `${style_};left:${guidePartentDom.left - guideDom.width - 8}px;z-index:998`;
							} else {
								style_ = `${style_};left:${res_.left - guideDom.width - 8 || 0}px;z-index:998`;
							}
						}
					}
					let top_guide = 0;
					top_guide = res_.top + (res_.height - guideDom.height) / 2;
					if (top_guide + guideDom.height > document.documentElement.clientHeight) {
						top_guide = res_.top + res_.height - guideDom.height + 4;
					} else if (top_guide < 0) {
						top_guide = 4;
					}
					style_ = `${style_};top:${top_guide}px;`;
					this.arrowStyle = `top:${res_.height / 2 + res_.top - 4 - top_guide}px`;
					if (this.guideStyle != style_) (this.guideStyle = style_), (this.guideDom = res_), (this.guideMounted = true);

					return;
				}

				if (document.documentElement.clientHeight - res_.top - res_.height >= guideDom.height + 8) {
					// 底部有足够的位置
					this.arrowDirection = 'up';
					if (!this.inside) {
						style_ = `${style_};top:${res_.top + res_.height + 8 || 0}px`;
					} else {
						if (this.outsideParent) {
							style_ = `${style_};top:${guidePartentDom.top + guidePartentDom.height + 8 || 0}px;z-index:998`;
						} else {
							style_ = `${style_};top:${res_.top + res_.height + 8 || 0}px;z-index:998`;
						}
					}
				} else {
					// 顶部
					this.arrowDirection = 'down';

					if (!this.inside) {
						style_ = `${style_};top:${res_.top - guideDom.height - 8}px`;
					} else {
						style_ = `${style_};right:${guidePartentDom.top + guidePartentDom.height - guideDom.height - 8
						}px;z-index:998`;
					}
					if (!this.inside) {
						style_ = `${style_};top:${res_.top - guideDom.height - 8 || 0}px`;
					} else {
						if (this.outsideParent) {
							style_ = `${style_};top:${guidePartentDom.top - guideDom.height - 8 || 0}px;z-index:998`;
						} else {
							style_ = `${style_};top:${res_.top - guideDom.height - 8 || 0}px;z-index:998`;
						}
					}
				}
				let left_guide = 0;
				left_guide = res_.left + (res_.width - guideDom.width) / 2;
				if (left_guide < 0) {
					left_guide = 4;
				}
				if (left_guide > document.documentElement.clientWidth - guideDom.width) {
					left_guide = res_.left + res_.width - guideDom.width + 4;
				}
				style_ = `${style_};left:${left_guide}px;`;

				this.arrowStyle = `left:${res_.width / 2 + res_.left - 4 - left_guide}px`;


				// this.arrowStyle = `left:${res_.width / 2 + res_.left - 4 - left_guide}px`;
				if (this.guideStyle != style_) (this.guideStyle = style_), (this.guideDom = res_), (this.guideMounted = true);
			}, 500);
			// 已舍弃 s
			// if (this.needCover && !this.copyDom) {
			// 	let dom_ = this.domObj ? this.domObj() : document.getElementById(`${this.domId}`);

			// 	dom_ && dom_.classList.add('guide-point');
			// }
			// 已舍弃 e
		},
		onLeftBtnClickHandler () {
			this.leftBtnFn && this.leftBtnFn();
		},
	},
});
</script>
<style lang="scss">
@import "./Guide.scss";
</style>
